package com.slofzx.nuoda.evaluation.version.builder;

import com.alibaba.fastjson.JSON;
import com.deepoove.poi.XWPFTemplate;
import com.deepoove.poi.config.Configure;
import com.deepoove.poi.plugin.pagination.PaginationRenderPolicy;
import com.deepoove.poi.plugin.table.LoopColumnTableRenderPolicy;
import com.deepoove.poi.util.PoitlIOUtils;
import com.slofzx.nuoda.common.exception.ServiceException;
import com.slofzx.nuoda.common.util.DataConvertUtil;
import com.slofzx.nuoda.common.vo.CompanyVO;
import com.slofzx.nuoda.common.vo.FileVO;
import com.slofzx.nuoda.evaluation.compute.data.vo.ComputeDetailDataVO;
import com.slofzx.nuoda.evaluation.entity.ComputeData;
import com.slofzx.nuoda.evaluation.project.entity.PlanInfo;
import com.slofzx.nuoda.evaluation.project.entity.ProjectInfo;
import com.slofzx.nuoda.evaluation.project.enums.EvaluationMethodEnum;
import com.slofzx.nuoda.evaluation.project.enums.OilDisplacementMethodEnum;
import com.slofzx.nuoda.evaluation.project.util.BusiUtil;
import com.slofzx.nuoda.evaluation.project.util.DoubleUtil;
import com.slofzx.nuoda.evaluation.version.vo.ComputeVersionVO;
import com.slofzx.nuoda.evaluation.version.vo.ProjectReportVO;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class IntegrationReportBuilder {

    /**
     * 建设单位列表
     */
    private CompanyVO buildOffice;
    /**
     * 建设单位ID名称map
     */
    private Map<String, String> officeNameMap;

    private String userOfficeId;

    protected static final String FEASIBILITY_TEMPLATE = "/template/integration_report.docx";
    private static final List<String> SCALE_2_KEY = Arrays.asList(  "YYSPL","YJPJDJRCYL","XMCWNBSYL_SH_ZB","SHNBSYL","ZTZSYLZB","ZBJJLRLZB","SQNBSYL","SQCWJXZ_XYJZ");
    private static final List<String> SCALE_1_KEY = Arrays.asList("XMTZHSQ_SH_ZB","CSWHJSS","SHTZHSQ","SQTZHSQ");
    private static final List<String> SCALE_0_KEY = Arrays.asList("SDSL", "YYZZSL", "TRQZZSL", "ZYS", "CSWHJSS", "JYFFJ","LDZJJKBL", "GDZCJKBL","GDZCZBJBL","XYJZSYL","LDZJZJYCBBL");

    protected ProjectInfo projectInfo;
    /**
     * 项目基本信息
     */
    protected List<ProjectInfo> projectList;
    /**
     * 项目版本数据
     */
    private ComputeVersionVO computeVersion;

    private PlanInfo plan;

    private List<ComputeVersionVO> computeVersionList;

    private ComputeDetailDataVO computeDetailData;

    private List<ComputeDetailDataVO> computeDetailDataList;

    private String fileName;

    public IntegrationReportBuilder fileName(String fileName) {
        this.fileName = fileName;
        return this;
    }

    public IntegrationReportBuilder plan(PlanInfo plan) {
        this.plan = plan;
        return this;
    }

    public IntegrationReportBuilder buildOffice(CompanyVO buildOffice) {
        this.buildOffice = buildOffice;
        return this;
    }

    public IntegrationReportBuilder userOfficeId(String userOfficeId) {
        this.userOfficeId = userOfficeId;
        return this;
    }

    public IntegrationReportBuilder officeNameMap (Map<String, String> officeNameMap) {
        this.officeNameMap = officeNameMap;
        return this;
    }

    // 利用利用 = 基建井数小计-钻井井数小计
    public IntegrationReportBuilder project(ProjectInfo projectInfo) {
        this.projectInfo = projectInfo;
        return this;
    }

    public IntegrationReportBuilder projectList(List<ProjectInfo> projectList) {
        this.projectList = projectList;
        return this;
    }

    public IntegrationReportBuilder computeVersion(ComputeVersionVO computeVersionVO) {
        this.computeVersion = computeVersionVO;
        return this;
    }

    public IntegrationReportBuilder computeVersionList(List<ComputeVersionVO> computeVersionList) {
        this.computeVersionList = computeVersionList;
        return this;
    }


    public IntegrationReportBuilder computeDetailData(ComputeDetailDataVO computeDetailData) {
        this.computeDetailData = computeDetailData;
        return this;
    }

    public IntegrationReportBuilder computeDetailDataList(List<ComputeDetailDataVO> computeDetailDataList) {
        this.computeDetailDataList = computeDetailDataList;
        return this;
    }

    /**
     * 构建下载文件
     *
     * @return
     */
    public FileVO build() {

        ProjectReportVO projectData = new ProjectReportVO();

        projectData.setBuiltUpCapacity(projectInfo.getBuiltUpCapacity());
        projectData.setDrillWellCount(projectInfo.getDrillWellCount());
        projectData.setEvaluationPeriod(projectInfo.getEvaluationPeriod());

        if (computeVersion.getIrrAfterTax() > 8D) {
            projectData.setFeasibility(true);
        } else {
            projectData.setNotFeasibility(true);
        }
        ComputeData computeData = null;
        if (computeDetailData != null && StringUtils.isNotEmpty(computeDetailData.getDetail())) {
            computeData = JSON.parseObject(computeDetailData.getDetail(), ComputeData.class);
        }
        Map<String, Object> groupDataMap = computeData.getGroupDataMap();
        if (computeData != null) {
            List<Map<String, Object>> yearDataList = new ArrayList<>();
            int cutoffYear = DataConvertUtil.parse2Int(groupDataMap.get("PJJZN"));
            if (cutoffYear - computeVersion.getCalculateYearStart() > 100) {
                throw new ServiceException("评价期大于100年，暂不支持导出", "评价期大于100年，暂不支持导出", computeVersion);
            }
            if (computeData.getResultDataMap() != null) {
                //第一年数据
                Map<String, Object> firstYearData = new HashMap<>();

                for (Map.Entry<String, Map<Integer, Object>> entry : computeData.getResultDataMap().entrySet()) {
                    final String key = entry.getKey();
                    Map<Integer, Object> yearDataMap = computeData.getResultDataMap().get(key);
                    if (yearDataMap != null) {
                        List<String> percentageList = Arrays.asList("LDZJZJYCBBL", "LDZJJKBL", "LDZJJKLL", "GDZCDKLL", "YYSPL", "SDSL", "YYZZSL", "TRQZZSL", "ZYS", "CSWHJSS", "JYFFJ", "YYFL", "GDZCJKBL", "GDZCDKLL", "XYJZSYL","GDZCZBJBL");
                        for (int year = computeVersion.getCalculateYearStart(); year <= computeVersion.getCalculateYearEnd(); year++) {
                            double yearData = DataConvertUtil.parse2Double(yearDataMap.get(year));
                            if (percentageList.contains(key)) {
                                yearData = yearData * 100;
                            }
                            if (year == computeVersion.getCalculateYearStart()) {
                                firstYearData.put(key, yearData);
                                if (SCALE_2_KEY.contains(key)) {
                                    firstYearData.put(key, DoubleUtil.getScaleString(yearData, 2));
                                }
                                if (SCALE_1_KEY.contains(key)) {
                                    firstYearData.put(key, DoubleUtil.getScaleString(yearData, 1));
                                }
                                if (SCALE_0_KEY.contains(key)) {
                                    firstYearData.put(key, DoubleUtil.getScaleString(yearData, 0));
                                }
                            }
                        }
                    }

                }
                // 处理合计含水率
                projectData.setFirstYearData(firstYearData);
            }
        }


        //导出数据
        String templatePath = FEASIBILITY_TEMPLATE;
        InputStream inputStream = IntegrationReportBuilder.class.getResourceAsStream(templatePath);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        // String fileName = plan.getName() + "可行性研究报告(经济评价).docx";
        FileVO result = new FileVO();
        result.setName(fileName);
        LoopColumnTableRenderPolicy columnPolicy = new LoopColumnTableRenderPolicy();
        PaginationRenderPolicy paginationRenderPolicy = new PaginationRenderPolicy();

        Configure configure = Configure.builder()
//
                .bind("pagination", paginationRenderPolicy)
                .build();
        Map<String, Object> wordDataMap = new HashMap<>();
        try {
            final Map<String, ProjectInfo> projectInfoMap = projectList.stream().filter(f -> StringUtils.isNotEmpty(f.getEvaluationMethod())).collect(Collectors.toMap(ProjectInfo::getEvaluationMethod, Function.identity(), (v1, v2) -> v1));
            // 计算详情map
            final Map<String, ComputeDetailDataVO> detailDataVOMap = computeDetailDataList.stream().collect(Collectors.toMap(ComputeDetailDataVO::getId, Function.identity()));
            // 构建评价方法下生成的计算详情map
            Map<String, ComputeData> computeDataMap = new HashMap<>();
            for (Map.Entry<String, ProjectInfo> infoEntry : projectInfoMap.entrySet()) {
                final ProjectInfo entryValue = infoEntry.getValue();
                if (entryValue != null) {
                    final String computeId = entryValue.getComputeId();
                    if (StringUtils.isNotEmpty(computeId)) {
                        final ComputeDetailDataVO computeDetailDataVO = detailDataVOMap.get(computeId);
                        if (computeDetailDataVO != null) {
                            computeDataMap.put(infoEntry.getKey(), JSON.parseObject(computeDetailDataVO.getDetail(), ComputeData.class));
                        }

                    }

                }
            }

            groupDataMap = parseMapBigDecimal2String(groupDataMap, 0);
            Map<String, Object> projectDataMap = JSON.parseObject(JSON.toJSONString(projectData), HashMap.class);
            if (projectInfo.getInfWellCount() != null && projectInfo.getInfWellCount() != 0) {
                projectDataMap.put("YJPJDJRCYL", (projectInfo.getStraightWellOutput() * (projectInfo.getInfWellCount() - projectInfo.getBuildHorizontalWellCount()) + projectInfo.getHorizontalWellOutput() * projectInfo.getBuildHorizontalWellCount()) / projectInfo.getInfWellCount());
            }
            projectDataMap = parseMapBigDecimal2String(projectDataMap, 0);
            wordDataMap.putAll(projectDataMap);
            wordDataMap.putAll(groupDataMap);
            wordDataMap.put("yearMonth", new SimpleDateFormat("yyyy年M月").format(new Date()));
            if (projectData.getDrillWellCount() != 0 && groupDataMap.get("ZTZZB") != null) {
                wordDataMap.put("DJTZ", Math.round(Double.parseDouble(groupDataMap.get("JSTZZB").toString()) / projectData.getDrillWellCount()));
            }
            if (projectData.getDrillWellCount() != 0 && groupDataMap.get("ZCTZHJ") != null) {
                wordDataMap.put("KFJDJTZ", Math.round(Double.parseDouble(groupDataMap.get("ZCTZHJ").toString()) / projectData.getDrillWellCount()));
            }
            if (projectData.getDrillWellCount() != 0 && groupDataMap.get("DMGCTZHJ") != null) {
                wordDataMap.put("DMGCDJTZ", Math.round(Double.parseDouble(groupDataMap.get("DMGCTZHJ").toString()) / projectData.getDrillWellCount()));
                wordDataMap.put("DMGCBWDCN",Math.round(Double.parseDouble(groupDataMap.get("DMGCTZHJ").toString()) / projectData.getBuiltUpCapacity()/100));
            }
            if (groupDataMap.get("JSTZZB") != null && projectData.getBuiltUpCapacity() != 0) {
                wordDataMap.put("BWDCN", Math.round(Double.parseDouble(groupDataMap.get("JSTZZB").toString()) / projectData.getBuiltUpCapacity() / 100));
            }
            XWPFTemplate.compile(inputStream, configure)
                    .render(wordDataMap).write(outputStream);
            result.setData(outputStream.toByteArray());
        } catch (IOException e) {
            throw new ServiceException("生成报告异常", "生成报告异常", e);
        } finally {
            PoitlIOUtils.closeLoggerQuietly(outputStream);
            PoitlIOUtils.closeLoggerQuietly(inputStream);
        }
        return result;
    }

    protected Map<String, Object> parseMapBigDecimal2String(Map<String, Object> dataMap, int digit) {
      //  List<String> oneDigitList = Arrays.asList("NCY", "NCY_1", "NZS", "DJRY");
        Map<String, Object> resultMap = new HashMap<>();
        if (dataMap == null) {
            return resultMap;
        }
        for (Map.Entry<String, Object> entry : dataMap.entrySet()) {
            if (entry.getValue() instanceof List) {
                List<Map<String, Object>> parseList = new ArrayList<>();
                List<Map<String, Object>> list = (List<Map<String, Object>>) entry.getValue();
                for (Map<String, Object> item : list) {
                    parseList.add(parseMapBigDecimal2String(item, 0));
                }
                resultMap.put(entry.getKey(), parseList);
                continue;
            }
            if (entry.getValue() instanceof BigDecimal) {
                if (SCALE_2_KEY.contains(entry.getKey())) {
                    resultMap.put(entry.getKey(), DoubleUtil.getScaleStringNew(((BigDecimal) entry.getValue()).doubleValue(), 2));
                } else if (SCALE_1_KEY.contains(entry.getKey())) {
                    resultMap.put(entry.getKey(), DoubleUtil.getScaleStringNew(((BigDecimal) entry.getValue()).doubleValue(), 1));
                } else if (entry.getKey().equals("builtUpCapacity")) {
                    resultMap.put(entry.getKey(), entry.getValue());
                } else {
                    resultMap.put(entry.getKey(), DoubleUtil.getScaleString(((BigDecimal) entry.getValue()).doubleValue(), digit));
                }
            } else if (entry.getValue() instanceof Double) {
                if (SCALE_2_KEY.contains(entry.getKey())) {
                    resultMap.put(entry.getKey(), DoubleUtil.getScaleStringNew((Double) entry.getValue(), 2));
                } else if (SCALE_1_KEY.contains(entry.getKey())) {
                    resultMap.put(entry.getKey(), DoubleUtil.getScaleStringNew((Double) entry.getValue(), 1));
                }else if (entry.getKey().equals("builtUpCapacity")) {
                    resultMap.put(entry.getKey(), entry.getValue());
                } else {
                    resultMap.put(entry.getKey(), DoubleUtil.getScaleString((Double) entry.getValue(), digit));
                }
            } else {
                resultMap.put(entry.getKey(), entry.getValue());
            }
        }
        return resultMap;
    }

}
